<template>
  <el-dialog
    v-model="dialogVisible"
    :title="dialogTitle"
    width="900px"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    @close="handleClose"
  >
    <el-form
      ref="formRef"
      :model="formData"
      :rules="formRules"
      label-width="120px"
      label-position="top"
    >
      <el-tabs v-model="activeTab" class="user-form-tabs">
        <!-- 基本信息 -->
        <el-tab-pane :label="$t('Identity.BasicInfo')" name="basic">
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item :label="$t('Identity.UserName')" prop="userName">
                <el-input
                  v-model="formData.userName"
                  :placeholder="$t('Identity.UserNamePlaceholder')"
                  :maxlength="50"
                  show-word-limit
                  @blur="checkUserNameAvailability"
                />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item :label="$t('Identity.Email')" prop="email">
                <el-input
                  v-model="formData.email"
                  :placeholder="$t('Identity.EmailPlaceholder')"
                  type="email"
                  @blur="checkEmailAvailability"
                />
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item :label="$t('Identity.Name')" prop="name">
                <el-input
                  v-model="formData.name"
                  :placeholder="$t('Identity.NamePlaceholder')"
                  :maxlength="50"
                />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item :label="$t('Identity.Surname')" prop="surname">
                <el-input
                  v-model="formData.surname"
                  :placeholder="$t('Identity.SurnamePlaceholder')"
                  :maxlength="50"
                />
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item :label="$t('Identity.PhoneNumber')" prop="phoneNumber">
                <el-input
                  v-model="formData.phoneNumber"
                  :placeholder="$t('Identity.PhoneNumberPlaceholder')"
                />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item :label="$t('Identity.Tenant')" prop="tenantId">
                <el-select
                  v-model="formData.tenantId"
                  :placeholder="$t('Identity.SelectTenant')"
                  clearable
                  filterable
                  :disabled="!currentTenantId && !isEdit"
                >
                  <el-option
                    v-for="tenant in tenants"
                    :key="tenant.id"
                    :label="tenant.name"
                    :value="tenant.id"
                  />
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>

          <el-row v-if="!isEdit" :gutter="20">
            <el-col :span="12">
              <el-form-item :label="$t('Identity.Password')" prop="password">
                <el-input
                  v-model="formData.password"
                  :placeholder="$t('Identity.PasswordPlaceholder')"
                  type="password"
                  show-password
                  @blur="checkPasswordStrength"
                />
                <div class="password-strength">
                  <div class="strength-bar">
                    <div
                      class="strength-fill"
                      :class="passwordStrength.class"
                      :style="{ width: passwordStrength.width }"
                    ></div>
                  </div>
                  <span class="strength-text" :class="passwordStrength.class">
                    {{ passwordStrength.text }}
                  </span>
                </div>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item :label="$t('Identity.ConfirmPassword')" prop="confirmPassword">
                <el-input
                  v-model="formData.confirmPassword"
                  :placeholder="$t('Identity.ConfirmPasswordPlaceholder')"
                  type="password"
                  show-password
                />
              </el-form-item>
            </el-col>
          </el-row>
        </el-tab-pane>

        <!-- 角色权限 -->
        <el-tab-pane :label="$t('Identity.Roles')" name="roles">
          <el-form-item :label="$t('Identity.UserRoles')">
            <el-checkbox-group v-model="formData.roleNames">
              <el-row :gutter="20">
                <el-col
                  v-for="role in roles"
                  :key="role.name"
                  :span="12"
                >
                  <el-checkbox
                    :value="role.name"
                    :disabled="role.name === 'admin' && !isEdit"
                  >
                    <div class="role-item">
                      <div class="role-name">{{ role.displayName }}</div>
                      <div class="role-description">{{ role.description }}</div>
                    </div>
                  </el-checkbox>
                </el-col>
              </el-row>
            </el-checkbox-group>
          </el-form-item>

          <el-form-item :label="$t('Identity.CustomPermissions')">
            <el-tree
              ref="permissionTreeRef"
              :data="permissionTree"
              :props="{ children: 'children', label: 'displayName' }"
              show-checkbox
              node-key="name"
              :default-checked-keys="formData.grantedPermissions"
              @check="handlePermissionCheck"
            />
          </el-form-item>
        </el-tab-pane>

        <!-- 个人资料 -->
        <el-tab-pane :label="$t('Identity.Profile')" name="profile">
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item :label="$t('Identity.Gender')">
                <el-radio-group v-model="formData.gender">
                  <el-radio value="male">{{ $t('Identity.Male') }}</el-radio>
                  <el-radio value="female">{{ $t('Identity.Female') }}</el-radio>
                  <el-radio value="other">{{ $t('Identity.Other') }}</el-radio>
                </el-radio-group>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item :label="$t('Identity.BirthDate')">
                <el-date-picker
                  v-model="formData.birthDate"
                  type="date"
                  :placeholder="$t('Identity.SelectBirthDate')"
                  style="width: 100%"
                />
              </el-form-item>
            </el-col>
          </el-row>

          <el-form-item :label="$t('Identity.Avatar')">
            <el-upload
              class="avatar-uploader"
              :action="uploadUrl"
              :show-file-list="false"
              :before-upload="beforeAvatarUpload"
              :on-success="handleAvatarSuccess"
              :headers="uploadHeaders"
            >
              <img v-if="formData.avatar" :src="formData.avatar" class="avatar" />
              <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
            </el-upload>
            <div class="upload-tip">
              {{ $t('Identity.AvatarUploadTip') }}
            </div>
          </el-form-item>

          <el-form-item :label="$t('Identity.Bio')">
            <el-input
              v-model="formData.bio"
              type="textarea"
              :rows="3"
              :placeholder="$t('Identity.BioPlaceholder')"
              :maxlength="500"
              show-word-limit
            />
          </el-form-item>

          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item :label="$t('Identity.Timezone')">
                <el-select
                  v-model="formData.timezone"
                  :placeholder="$t('Identity.SelectTimezone')"
                  filterable
                >
                  <el-option
                    v-for="tz in timezones"
                    :key="tz.value"
                    :label="tz.label"
                    :value="tz.value"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item :label="$t('Identity.Language')">
                <el-select
                  v-model="formData.language"
                  :placeholder="$t('Identity.SelectLanguage')"
                >
                  <el-option label="中文" value="zh-CN" />
                  <el-option label="English" value="en-US" />
                  <el-option label="日本語" value="ja-JP" />
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>
        </el-tab-pane>

        <!-- 安全设置 -->
        <el-tab-pane :label="$t('Identity.Security')" name="security">
          <el-form-item :label="$t('Identity.TwoFactor')">
            <el-switch
              v-model="formData.twoFactorEnabled"
              :active-text="$t('Identity.Enabled')"
              :inactive-text="$t('Identity.Disabled')"
            />
            <div class="form-help">
              <el-alert
                :title="$t('Identity.TwoFactorHelp')"
                type="info"
                :closable="false"
                show-icon
              />
            </div>
          </el-form-item>

          <el-form-item :label="$t('Identity.LockoutEnabled')">
            <el-switch
              v-model="formData.lockoutEnabled"
              :active-text="$t('Identity.Enabled')"
              :inactive-text="$t('Identity.Disabled')"
            />
          </el-form-item>

          <el-row v-if="formData.lockoutEnabled" :gutter="20">
            <el-col :span="12">
              <el-form-item :label="$t('Identity.LockoutDuration')">
                <el-input-number
                  v-model="formData.lockoutDurationMinutes"
                  :min="1"
                  :max="1440"
                  :step="1"
                  controls-position="right"
                />
                <span class="input-suffix">{{ $t('Identity.Minutes') }}</span>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item :label="$t('Identity.MaxFailedAccessAttempts')">
                <el-input-number
                  v-model="formData.maxFailedAccessAttempts"
                  :min="1"
                  :max="10"
                  :step="1"
                  controls-position="right"
                />
              </el-form-item>
            </el-col>
          </el-row>

          <el-form-item :label="$t('Identity.ActiveSessions')">
            <div v-if="activeSessions.length > 0" class="sessions-list">
              <div
                v-for="session in activeSessions"
                :key="session.id"
                class="session-item"
              >
                <div class="session-info">
                  <div class="session-device">{{ session.device }}</div>
                  <div class="session-time">{{ formatTime(session.loginTime) }}</div>
                  <div class="session-ip">{{ session.ipAddress }}</div>
                </div>
                <el-button
                  type="danger"
                  size="small"
                  plain
                  @click="revokeSession(session.id)"
                >
                  {{ $t('Identity.Revoke') }}
                </el-button>
              </div>
            </div>
            <div v-else class="no-sessions">
              {{ $t('Identity.NoActiveSessions') }}
            </div>
          </el-form-item>
        </el-tab-pane>
      </el-tabs>
    </el-form>

    <template #footer>
      <div class="dialog-footer">
        <el-button @click="handleClose">{{ $t('Common.Cancel') }}</el-button>
        <el-button type="primary" :loading="loading" @click="handleSubmit">
          {{ isEdit ? $t('Common.Update') : $t('Common.Create') }}
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted } from 'vue'
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import { userService } from '@/services/user.service'
import { tenantService } from '@/services/tenant.service'
import { authService } from '@/services/AuthService'
import { abpService } from '@/services/abp.service'
import type { User, Role, CreateUpdateUserInput } from '@/types/abp'

interface Props {
  modelValue: boolean
  user?: User | null
}

interface Emits {
  (e: 'update:modelValue', value: boolean): void
  (e: 'success'): void
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()

const formRef = ref<FormInstance>()
const permissionTreeRef = ref()
const loading = ref(false)
const activeTab = ref('basic')
const tenants = ref<any[]>([])
const roles = ref<Role[]>([])
const permissionTree = ref<any[]>([])
const activeSessions = ref<any[]>([])

const dialogVisible = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
})

const isEdit = computed(() => !!props.user?.id)

const dialogTitle = computed(() =>
  isEdit.value ? $t('Identity.EditUser') : $t('Identity.CreateUser')
)

const currentTenantId = computed(() => abpService.getCurrentTenant()?.id)

const uploadUrl = computed(() => '/api/files/avatar')
const uploadHeaders = computed(() => ({
  Authorization: `Bearer ${authService.getToken()}`
}))

// 表单数据
const formData = reactive({
  userName: '',
  email: '',
  name: '',
  surname: '',
  phoneNumber: '',
  password: '',
  confirmPassword: '',
  tenantId: '',
  roleNames: [] as string[],
  grantedPermissions: [] as string[],
  gender: 'male',
  birthDate: null,
  avatar: '',
  bio: '',
  timezone: 'UTC',
  language: 'zh-CN',
  twoFactorEnabled: false,
  lockoutEnabled: true,
  lockoutDurationMinutes: 30,
  maxFailedAccessAttempts: 5
})

// 密码强度计算
const passwordStrength = computed(() => {
  if (!formData.password) return { width: '0%', class: '', text: '' }

  let strength = 0
  if (formData.password.length >= 8) strength++
  if (/[a-z]/.test(formData.password)) strength++
  if (/[A-Z]/.test(formData.password)) strength++
  if (/[0-9]/.test(formData.password)) strength++
  if (/[^A-Za-z0-9]/.test(formData.password)) strength++

  const strengthMap = [
    { width: '20%', class: 'weak', text: $t('Identity.PasswordWeak') },
    { width: '40%', class: 'weak', text: $t('Identity.PasswordWeak') },
    { width: '60%', class: 'medium', text: $t('Identity.PasswordMedium') },
    { width: '80%', class: 'strong', text: $t('Identity.PasswordStrong') },
    { width: '100%', class: 'strong', text: $t('Identity.PasswordVeryStrong') }
  ]

  return strengthMap[Math.min(strength, 4)]
})

// 表单验证规则
const formRules: FormRules = {
  userName: [
    { required: true, message: $t('Identity.UserNameRequired'), trigger: 'blur' },
    { min: 3, max: 50, message: $t('Identity.UserNameLength'), trigger: 'blur' },
    { pattern: /^[a-zA-Z0-9_]+$/, message: $t('Identity.UserNamePattern'), trigger: 'blur' }
  ],
  email: [
    { required: true, message: $t('Identity.EmailRequired'), trigger: 'blur' },
    { type: 'email', message: $t('Identity.EmailFormat'), trigger: 'blur' }
  ],
  password: [
    { required: !isEdit.value, message: $t('Identity.PasswordRequired'), trigger: 'blur' },
    { min: 8, message: $t('Identity.PasswordLength'), trigger: 'blur' }
  ],
  confirmPassword: [
    { required: !isEdit.value, message: $t('Identity.ConfirmPasswordRequired'), trigger: 'blur' },
    {
      validator: (rule, value, callback) => {
        if (value !== formData.password) {
          callback(new Error($t('Identity.PasswordMismatch')))
        } else {
          callback()
        }
      },
      trigger: 'blur'
    }
  ]
}

// 时区选项
const timezones = [
  { label: 'UTC (UTC+0)', value: 'UTC' },
  { label: '北京时间 (UTC+8)', value: 'Asia/Shanghai' },
  { label: '东京时间 (UTC+9)', value: 'Asia/Tokyo' },
  { label: '纽约时间 (UTC-5)', value: 'America/New_York' },
  { label: '伦敦时间 (UTC+0)', value: 'Europe/London' }
]

// 初始化数据
const initializeData = async () => {
  try {
    // 加载租户列表（仅限主机管理员）
    if (!currentTenantId.value && abpService.hasPermission('Identity.Tenants')) {
      const tenantResult = await tenantService.getTenantList({ maxResultCount: 1000 })
      tenants.value = tenantResult.items
    }

    // 加载角色列表
    const roleResult = await userService.getRoleList()
    roles.value = roleResult.items

    // 加载权限树
    const permissionResult = await userService.getPermissionList()
    permissionTree.value = buildPermissionTree(permissionResult.items)

    // 如果是编辑模式，加载用户会话
    if (isEdit.value) {
      const sessions = await userService.getUserSessions(props.user!.id)
      activeSessions.value = sessions.items
    }
  } catch (error) {
    console.error('初始化用户表单数据失败:', error)
  }
}

// 构建权限树
const buildPermissionTree = (permissions: any[]) => {
  const tree: any[] = []
  const parentMap = new Map()

  // 首先构建父级节点映射
  permissions.forEach(permission => {
    if (!permission.parentName) {
      parentMap.set(permission.name, {
        name: permission.name,
        displayName: permission.displayName,
        description: permission.description,
        children: []
      })
    }
  })

  // 添加子节点
  permissions.forEach(permission => {
    if (permission.parentName && parentMap.has(permission.parentName)) {
      parentMap.get(permission.parentName).children.push({
        name: permission.name,
        displayName: permission.displayName,
        description: permission.description
      })
    } else if (!permission.parentName) {
      tree.push(parentMap.get(permission.name))
    }
  })

  return tree
}

// 监听用户数据变化
watch(() => props.user, (newUser) => {
  if (newUser) {
    Object.assign(formData, {
      userName: newUser.userName || '',
      email: newUser.email || '',
      name: newUser.name || '',
      surname: newUser.surname || '',
      phoneNumber: newUser.phoneNumber || '',
      tenantId: newUser.tenantId || '',
      roleNames: newUser.roleNames || [],
      grantedPermissions: newUser.grantedPermissions || [],
      gender: newUser.gender || 'male',
      birthDate: newUser.birthDate ? new Date(newUser.birthDate) : null,
      avatar: newUser.avatar || '',
      bio: newUser.bio || '',
      timezone: newUser.timezone || 'UTC',
      language: newUser.language || 'zh-CN',
      twoFactorEnabled: newUser.twoFactorEnabled || false,
      lockoutEnabled: newUser.lockoutEnabled || true,
      lockoutDurationMinutes: newUser.lockoutDurationMinutes || 30,
      maxFailedAccessAttempts: newUser.maxFailedAccessAttempts || 5
    })
  } else {
    resetForm()
  }
}, { immediate: true })

// 重置表单
const resetForm = () => {
  Object.assign(formData, {
    userName: '',
    email: '',
    name: '',
    surname: '',
    phoneNumber: '',
    password: '',
    confirmPassword: '',
    tenantId: currentTenantId.value || '',
    roleNames: [],
    grantedPermissions: [],
    gender: 'male',
    birthDate: null,
    avatar: '',
    bio: '',
    timezone: 'UTC',
    language: 'zh-CN',
    twoFactorEnabled: false,
    lockoutEnabled: true,
    lockoutDurationMinutes: 30,
    maxFailedAccessAttempts: 5
  })
  activeTab.value = 'basic'
}

// 检查用户名可用性
const checkUserNameAvailability = async () => {
  if (!formData.userName || isEdit.value) return

  try {
    const users = await userService.getUserList({ filter: formData.userName })
    if (users.items.some(u => u.userName.toLowerCase() === formData.userName.toLowerCase())) {
      formRef.value?.validateField('userName')
      ElMessage.warning($t('Identity.UserNameExists'))
    }
  } catch (error) {
    console.error('检查用户名可用性失败:', error)
  }
}

// 检查邮箱可用性
const checkEmailAvailability = async () => {
  if (!formData.email || isEdit.value) return

  try {
    const users = await userService.getUserList({ filter: formData.email })
    if (users.items.some(u => u.email.toLowerCase() === formData.email.toLowerCase())) {
      formRef.value?.validateField('email')
      ElMessage.warning($t('Identity.EmailExists'))
    }
  } catch (error) {
    console.error('检查邮箱可用性失败:', error)
  }
}

// 检查密码强度
const checkPasswordStrength = () => {
  // 密码强度通过 computed 计算显示
}

// 处理权限选择
const handlePermissionCheck = (data: any, checked: any) => {
  formData.grantedPermissions = checked.checkedKeys
}

// 头像上传前验证
const beforeAvatarUpload = (file: File) => {
  const isImage = file.type.startsWith('image/')
  const isLt2M = file.size / 1024 / 1024 < 2

  if (!isImage) {
    ElMessage.error($t('Identity.AvatarFormatError'))
    return false
  }
  if (!isLt2M) {
    ElMessage.error($t('Identity.AvatarSizeError'))
    return false
  }
  return true
}

// 头像上传成功
const handleAvatarSuccess = (response: any) => {
  formData.avatar = response.url
  ElMessage.success($t('Identity.AvatarUploadSuccess'))
}

// 撤销会话
const revokeSession = async (sessionId: string) => {
  try {
    await ElMessageBox.confirm(
      $t('Identity.RevokeSessionConfirm'),
      $t('Identity.RevokeSession'),
      {
        confirmButtonText: $t('Common.Confirm'),
        cancelButtonText: $t('Common.Cancel'),
        type: 'warning'
      }
    )

    await userService.revokeSession(props.user!.id, sessionId)
    ElMessage.success($t('Identity.RevokeSessionSuccess'))

    // 重新加载会话列表
    const sessions = await userService.getUserSessions(props.user!.id)
    activeSessions.value = sessions.items
  } catch (error: any) {
    if (error !== 'cancel') {
      console.error('撤销会话失败:', error)
      ElMessage.error($t('Identity.RevokeSessionFailed'))
    }
  }
}

// 格式化时间
const formatTime = (time: string) => {
  return new Date(time).toLocaleString()
}

// 处理提交
const handleSubmit = async () => {
  if (!formRef.value) return

  try {
    await formRef.value.validate()

    loading.value = true

    const userRequest: CreateUpdateUserInput = {
      userName: formData.userName,
      email: formData.email,
      name: formData.name,
      surname: formData.surname,
      phoneNumber: formData.phoneNumber,
      password: formData.password,
      tenantId: formData.tenantId,
      roleNames: formData.roleNames,
      grantedPermissions: formData.grantedPermissions,
      gender: formData.gender,
      birthDate: formData.birthDate,
      avatar: formData.avatar,
      bio: formData.bio,
      timezone: formData.timezone,
      language: formData.language,
      twoFactorEnabled: formData.twoFactorEnabled,
      lockoutEnabled: formData.lockoutEnabled,
      lockoutDurationMinutes: formData.lockoutDurationMinutes,
      maxFailedAccessAttempts: formData.maxFailedAccessAttempts
    }

    if (isEdit.value) {
      await userService.updateUser(props.user!.id, userRequest)
      ElMessage.success($t('Identity.UpdateUserSuccess'))
    } else {
      await userService.createUser(userRequest)
      ElMessage.success($t('Identity.CreateUserSuccess'))
    }

    emit('success')
    handleClose()
  } catch (error: any) {
    console.error('保存用户失败:', error)

    if (error.response?.data?.error?.details) {
      ElMessage.error(error.response.data.error.details)
    } else if (error.response?.data?.error?.message) {
      ElMessage.error(error.response.data.error.message)
    } else {
      ElMessage.error($t('Identity.SaveUserFailed'))
    }
  } finally {
    loading.value = false
  }
}

// 处理关闭
const handleClose = () => {
  if (loading.value) return

  dialogVisible.value = false
  setTimeout(() => {
    formRef.value?.resetFields()
    resetForm()
  }, 300)
}

onMounted(() => {
  initializeData()
})
</script>

<style scoped>
.user-form-tabs {
  margin: -20px;
}

.form-help {
  margin-top: 5px;
  font-size: 12px;
}

.password-strength {
  margin-top: 5px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.strength-bar {
  flex: 1;
  height: 4px;
  background-color: #f0f0f0;
  border-radius: 2px;
  overflow: hidden;
}

.strength-fill {
  height: 100%;
  transition: width 0.3s ease, background-color 0.3s ease;
}

.strength-fill.weak {
  background-color: #f56c6c;
}

.strength-fill.medium {
  background-color: #e6a23c;
}

.strength-fill.strong {
  background-color: #67c23a;
}

.strength-text {
  font-size: 12px;
  font-weight: 500;
}

.strength-text.weak {
  color: #f56c6c;
}

.strength-text.medium {
  color: #e6a23c;
}

.strength-text.strong {
  color: #67c23a;
}

.avatar-uploader {
  text-align: center;
}

.avatar-uploader .avatar {
  width: 100px;
  height: 100px;
  border-radius: 50%;
  object-fit: cover;
}

.avatar-uploader .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 50%;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  width: 100px;
  height: 100px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.avatar-uploader .el-upload:hover {
  border-color: #409eff;
}

.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
}

.upload-tip {
  margin-top: 5px;
  font-size: 12px;
  color: #909399;
}

.role-item {
  margin-left: 8px;
}

.role-name {
  font-weight: 500;
  color: #303133;
}

.role-description {
  font-size: 12px;
  color: #909399;
  margin-top: 2px;
}

.sessions-list {
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  padding: 10px;
  max-height: 300px;
  overflow-y: auto;
}

.session-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px;
  border-bottom: 1px solid #f0f0f0;
}

.session-item:last-child {
  border-bottom: none;
}

.session-device {
  font-weight: 500;
  color: #303133;
}

.session-time {
  font-size: 12px;
  color: #909399;
  margin-top: 2px;
}

.session-ip {
  font-size: 12px;
  color: #909399;
}

.no-sessions {
  text-align: center;
  color: #909399;
  padding: 20px;
}

.dialog-footer {
  text-align: right;
}

.input-suffix {
  margin-left: 5px;
  font-size: 12px;
  color: #909399;
}

:deep(.el-tabs__content) {
  padding: 20px;
}

:deep(.el-form-item__label) {
  font-weight: 500;
}

:deep(.el-input-number) {
  width: 100%;
}

:deep(.el-checkbox-group) {
  width: 100%;
}

:deep(.el-tree) {
  max-height: 300px;
  overflow-y: auto;
}
</style>